/*
 * PopupImage.cpp
 *
 *  Created on: Jul 7, 2013
 *      Author: guillou
 */

#include <PopupOSAL.hpp>
#include <PopupLoggerUI.hpp>
#include "PopupImageViewer.hpp"
#include "PopupImageViewerFx.hpp"
#include "PopupImage.hpp"
#include "PopupSettings.hpp"

using namespace PopupUtils;

PopupImage::PopupImage(PopupImageViewer *p_parent,
                       QString p_imagePath,
                       QString p_senderName,
                       bool p_forceFullscreen)
: parent(p_parent), valid(false), m_imagePath(p_imagePath),
  m_sender(p_senderName), m_image(0),
  currentImageWidth(0), currentImageHeight(0),
  finalImageWidth(0), finalImageHeight(0),
  currentX(0), currentY(0), finalX(0), finalY(0), nbDynamicFx(0)
{
  float _shrink = 1.0;
  QRect _rect = QApplication::desktop()->availableGeometry();
  int _screenWidth  = _rect.width();
  int _screenHeight = _rect.height();
  PopupSettings *_settings = PopupSettings::instance();

  // Instantiate image
  m_image = new QImage(m_imagePath);

  // Oops we failed
  if (m_image->isNull())
  {
    error("Failed to instantiate QImage %s",
          m_imagePath.toStdString().c_str());
  }
  // Well, that's OK so far
  else
  {
    // Compute image size
    //-------------------

    finalImageWidth  = m_image->width();
    finalImageHeight = m_image->height();

    // Fullscreen : make image as big as possible
    // No other FX can be merged
    if (p_forceFullscreen)
    {
      if (finalImageHeight < _screenHeight) {
        _shrink = ((float) _screenHeight) / ((float) finalImageHeight);
      } else {
        _shrink = ((float) finalImageHeight / (float) _screenHeight);
      }
      if (finalImageWidth > _screenWidth) {
        _shrink  = POPUP_MACRO_MIN(_shrink, ((float) _screenWidth) / ((float) finalImageWidth));
      }
    }

    // Default: use image native size, and make it smaller in case it cannot
    // fit the screen
    else
    {
      if (finalImageWidth > _screenWidth) {
        _shrink = ((float) _screenWidth) / ((float) finalImageWidth);
      }
      if (finalImageHeight > _screenHeight) {
        _shrink  = POPUP_MACRO_MIN(_shrink, ((float) _screenHeight) / ((float) finalImageHeight));
      }
    }

    if (_shrink != 1.0)
    {
      finalImageWidth  *= _shrink;
      finalImageHeight *= _shrink;
    }

    currentImageWidth = finalImageWidth;
    currentImageHeight = finalImageHeight;

    // Compute image position
    //-----------------------

    PopupGui::Position _pos;
    if (p_forceFullscreen)
    {
      // Centered by default in case we are in full screen mode
      _pos |= PopupGui::POPUP_HCENTER;
      _pos |= PopupGui::POPUP_VCENTER;
    }
    else
    {
      // Use settings information otherwise
      _pos = _settings->getImageViewerPosition();
    }

    //-------- X position

    if (_pos.testFlag(PopupGui::POPUP_LEFT)) {
      finalX = 10;
    } else if (_pos.testFlag(PopupGui::POPUP_HCENTER)) {
      finalX = (_screenWidth - currentImageWidth) / 2;
    } else if (_pos.testFlag(PopupGui::POPUP_RIGHT)) {
      finalX = _screenWidth - currentImageWidth;
    }

    //-------- Y position

    if (_pos.testFlag(PopupGui::POPUP_TOP)) {
      finalY = 10;
    } else if (_pos.testFlag(PopupGui::POPUP_VCENTER)) {
      finalY = (_screenHeight - currentImageHeight) / 2;
    } else if (_pos.testFlag(PopupGui::POPUP_BOTTOM)) {
      finalY = _screenHeight - currentImageHeight;
    }

    currentX = finalX;
    currentY = finalY;

    // Instantiate FX
    //------------------------

    // Some FX are disabled when forced fullscreen is toggled.
    if (!p_forceFullscreen)
    {
      if (_settings->isImageViewerTransitionFxEnabled())
      {
        effects.push_back(new PopupTransitionFx(this));
        nbDynamicFx++;
      }
      if (_settings->isImageViewerOpacityFxEnabled())
      {
        effects.push_back(new PopupOpacityFx(this));
        nbDynamicFx++;
      }
      if (_settings->isImageViewerZoomFxEnabled())
      {
        effects.push_back(new PopupZoomFx(this));
        nbDynamicFx++;
      }
    }

    if (m_sender.length() > 0)
    {
      effects.push_back(new PopupImageTextOverlayFx(this));
    }

    // This image is ready to display
    valid = true;
  }
}

PopupImage::~PopupImage()
{
  // Destroy QImage
  if (m_image != 0) delete m_image;

  // Destroy effects
  vector_foreach(effects, PopupImageFx*, _itFx)
  {
    delete *_itFx;
  }
}

void PopupImage::paint(QPainter & p_painter)
{
  QRect _rect(0, 0, currentImageWidth, currentImageHeight);
  p_painter.drawImage(_rect, *m_image);

  vector_foreach(effects, PopupImageFx*, _itFx)
  {
    (void) (*_itFx)->paint(p_painter);
  }
}

bool PopupImage::applyFx()
{
  bool _needSomeMoreTimeToFinish = false;
  vector_foreach(effects, PopupImageFx*, _itFx)
  {
    if ((*_itFx)->apply()) {
      _needSomeMoreTimeToFinish = true;
    }
  }
  return _needSomeMoreTimeToFinish;
}
